<?php

namespace App\Ability;

use Hyperf\Contract\ValidatorInterface;
use Hyperf\Utils\Contracts\MessageBag;
use Hyperf\Validation\Contract\ValidatorFactoryInterface;
use Hyperf\Validation\UnauthorizedException;

/**
 * 逻辑必须是可以校验请求参数，然后将参数作为对象的属性值
 */
trait Verifiable
{
    use Fillable;
    /**
     * @var ValidatorInterface
     */
    public $validator;

    /**
     * 验证请求，返回验证结果
     * @param array $params
     * @return bool
     */
    public function validate(array $params) :bool
    {
        $factory = make(ValidatorFactoryInterface::class);

        $this->validator = $factory->make($params, $this->rules(), $this->messages(), $this->attributes());

        if(!$this->validator->passes()){
            return false;
        }

        //使用通过验证的数据初始化逻辑对象
        $this->fill($this->validator->validated());

        //访问授权的检验
        if (! $this->passesAuthorization()) {
            $this->failedAuthorization();
        }

        return true;
    }

    /**
     * 获取验证器的错误
     * @return MessageBag
     */
    public function getErrors():MessageBag
    {
        return $this->validator->errors();
    }

    /**
     * Get custom rules to validator.
     */
    public function rules(): array
    {
        return [];
    }

    /**
     * Get custom messages for validator errors.
     */
    public function messages(): array
    {
        return [];
    }

    /**
     * Get custom attributes for validator errors.
     */
    public function attributes(): array
    {
        return [];
    }

    /**
     * 检查权限
     * @return bool
     */
    protected function passesAuthorization(): bool
    {
        if (method_exists($this, 'authorize')) {
            return call_user_func_array([$this, 'authorize'], []);
        }
        return true;
    }

    /**
     * 权限检查失败
     */
    protected function failedAuthorization()
    {
        throw new UnauthorizedException('This action is unauthorized.');
    }
}